package at.codejedi.sto.controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import at.codejedi.sto.config.Configuration;
import at.codejedi.sto.controller.combat.CombatLogController;
import at.codejedi.sto.controller.combat.ICombatMainController;
import at.codejedi.sto.gui.IMainView;
import at.codejedi.sto.gui.MainFrame;
import at.codejedi.sto.gui.combat.CombatLogView;
import at.codejedi.sto.gui.combat.ICombatLogView;
import at.codejedi.sto.model.MainModel;

public class MainController implements ICombatMainController {
	class CloseCurrentDetailsViewActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			closeDetailView(getSelectedCombatLogView());
		}

	}

	class CombatLogFileOpenListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			File startPath = model.getLastFileChooserPath();

			File file = view.chooseCombatFilePath(startPath);
			if (file == null)
				return;
			model.setLastFileChooserPath(file);
			openCombatLogFile(file);

		}
	}

	class CopyDetailsToClipboardActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			getSelectedCombatLogView().copyDetailsToClipboard();
		}

	}

	class CreateBuildActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			getSelectedCombatLogView().createNewBuild();
		}

	}

	private static MainModel loadModel(IMainView view)
			throws FileNotFoundException, JAXBException {
		File mainModelFile = Configuration.getPropertyFile("mainModel.xml");
		MainModel model = new MainModel();
		if (mainModelFile == null || !mainModelFile.exists()) {
			return model;
		}

		FileInputStream fileInputStream = new java.io.FileInputStream(
				mainModelFile);

		JAXBContext contextB = JAXBContext.newInstance(MainModel.class);
		Unmarshaller unmarshallerB = contextB.createUnmarshaller();
		model = (MainModel) unmarshallerB.unmarshal(fileInputStream);

		view.setRecentFilesList(model.getRecentOpenedFiles());

		return model;
	}

	private MainModel model;

	private ICombatLogView selectedCombatLogView;

	private IMainView view;

	public MainController() {
		view = new MainFrame();

		try {
			model = loadModel(view);
		} catch (FileNotFoundException e) {
			showException(e);
		} catch (JAXBException ex) {
			showException(ex);
		}

		addListener();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.codejedi.sto.controller.IMainController#addFileToRecentOpenedFiles
	 * (java.io.File)
	 */
	@Override
	public void addFileToRecentOpenedFiles(File file) {
		List<File> recentOpenedFiles = model.getRecentOpenedFiles();
		if (recentOpenedFiles.size() >= 5)
			recentOpenedFiles.remove(recentOpenedFiles.size() - 1);
		if (recentOpenedFiles.contains(file))
			return;
		model.getRecentOpenedFiles().add(file);
		view.setRecentFilesList(model.getRecentOpenedFiles());
	}

	private void addListener() {
		view.openCombatLogFile(new CombatLogFileOpenListener());
		view.copyDetailsToClipboard(new CopyDetailsToClipboardActionListener());
		view.selectOpenCombatLogFile(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				JTabbedPane source = (JTabbedPane) e.getSource();
				setSelectedCombatLogView((CombatLogView) source
						.getSelectedComponent());
			}

		});
		view.addWindowClosingActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				persistModel();
			}
		});
		view.addRecentFileSelectedActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String filePath = e.getActionCommand();
				openCombatLogFile(new File(filePath));

			}
		});

		view.addCloseDetailsActionListener(new CloseCurrentDetailsViewActionListener());

		view.createShipBuild(new CreateBuildActionListener());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.codejedi.sto.controller.IMainController#closeDetailView(at.codejedi
	 * .sto.gui.combat.ICombatLogView)
	 */
	@Override
	public void closeDetailView(ICombatLogView combatLogView) {
		view.removeCombatLogView(combatLogView);
	}

	public ICombatLogView getSelectedCombatLogView() {
		return selectedCombatLogView;
	}

	public void openCombatLogFile(File file) {

		try {
			CombatLogController controller = new CombatLogController(file, this);
			ICombatLogView combatLogView = controller.getView();
			view.addCombatLogView(file.getName(), combatLogView);

		} catch (Throwable e1) {
			view.showException(e1);
		}
	}

	public void openCombatLogFile(String filePath) {
		try {
			openCombatLogFileInternal(filePath);
		} catch (FileNotFoundException e) {
			view.showException(e);
		}
	}

	private void openCombatLogFileInternal(String filePath)
			throws FileNotFoundException {
		if (filePath == null)
			throw new NullPointerException(
					"file Path is not allowed to be empty");
		File file = new File(filePath);
		if (!file.exists())
			throw new FileNotFoundException(filePath);
		openCombatLogFile(file);
	}

	public void persistModel() {
		try {
			File mainModelFile = Configuration.getPropertyFile("mainModel.xml");
			JAXBContext context = JAXBContext.newInstance(MainModel.class);

			Marshaller m = context.createMarshaller();
			m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			m.marshal(model, mainModelFile);
		} catch (JAXBException ex) {

		}
	}

	public void setSelectedCombatLogView(ICombatLogView selectedCombatLogView) {
		this.selectedCombatLogView = selectedCombatLogView;
		boolean enabeled = selectedCombatLogView != null;
		view.copyDetailsToClipboard(enabeled);
		view.closeDetails(enabeled);
		view.persistCombatLogEnabled(enabeled);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.codejedi.sto.controller.IMainController#showException(java.lang.Throwable
	 * )
	 */
	@Override
	public void showException(Throwable t) {
		view.showException(t);
		t.printStackTrace();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.codejedi.sto.controller.IMainController#showInfo(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public void showInfo(String title, String message) {
		view.showInfo(title, message);
	}

	public void showView() {
		view.showView();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * at.codejedi.sto.controller.IMainController#showWarning(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public void showWarning(String title, String message) {
		view.showWarning(title, message);
	}
}
